package com.kcwl.carrier.application.service;

import cn.hutool.core.util.ObjectUtil;
import com.kcwl.carrier.domain.entity.CarrierGroupInfo;
import com.kcwl.carrier.domain.entity.CarrierInfo;
import com.kcwl.carrier.domain.entity.CarrierMappingInfo;
import com.kcwl.carrier.domain.service.*;
import com.kcwl.carrier.infrastructure.enums.AuditAuthenticationStatusEnum;
import com.kcwl.carrier.infrastructure.enums.CarrierStatusEnum;
import com.kcwl.carrier.infrastructure.enums.CarrierUseErrorCodeEnum;
import com.kcwl.carrier.infrastructure.exceptions.CarrierUserException;
import com.kcwl.carrier.interfaces.command.*;
import com.kcwl.carrier.interfaces.dto.CarrierDTO;
import com.kcwl.carrier.interfaces.dto.CarrierGroupInfoDTO;
import com.kcwl.carrier.interfaces.dto.CarrierListDTO;
import com.kcwl.carrier.interfaces.dto.VehicleInfoDTO;
import com.kcwl.carrier.interfaces.query.CarrierListQuery;
import com.kcwl.carrier.interfaces.query.IdQuery;
import com.kcwl.carrier.interfaces.query.UserIdQuery;
import com.kcwl.ddd.infrastructure.utils.KcPageConverter;
import com.kcwl.ddd.interfaces.dto.PageInfoDTO;
import com.kcwl.framework.utils.JsonUtil;
import com.kcwl.framework.utils.KcBeanConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @author healen
 */
@Service
@Slf4j
public class CarrierGroupApplicationService {

    @Autowired
    private CarrierGroupDomainService carrierGroupDomainService;
    @Autowired
    private CarrierMappingDomainService carrierMappingDomainService;
    @Autowired
    private VehicleInfoDomainService vehicleInfoDomainService;
    @Autowired
    private CarrierInfoDomainService carrierInfoDomainService;
    @Autowired
    CarrierDriverDomainService carrierDriverDomainService;


    @Transactional(rollbackFor = Exception.class)
    public Boolean addGroup(CarrierGroupAddCommand groupAddCommand) {
        carrierGroupDomainService.addGroup(groupAddCommand);
        return Boolean.TRUE;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean updateGroup(CarrierGroupUpdateCommand groupUpdateCommand) {
        CarrierGroupInfo info = carrierGroupDomainService.groupInfo(groupUpdateCommand.getId());
        if (ObjectUtil.isEmpty(info)) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.DATA_NOT_EXIST);
        }

        carrierGroupDomainService.updateGroup(groupUpdateCommand);
        return Boolean.TRUE;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteGroup(Long id) {
        CarrierGroupInfo info = carrierGroupDomainService.groupInfo(id);
        if (ObjectUtil.isEmpty(info)) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.DATA_NOT_EXIST);
        }

        carrierGroupDomainService.deleteGroup(id);
        return Boolean.TRUE;
    }

    public CarrierGroupInfoDTO groupInfo(Long id) {
        return KcBeanConverter.toBean(carrierGroupDomainService.groupInfo(id), CarrierGroupInfoDTO.class);
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean stopOrder(IdCommand command) {
        CarrierMappingInfo info = carrierMappingDomainService.getCarrierMapingInfo(command.getId());
        if (ObjectUtil.isEmpty(info)) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.DATA_NOT_EXIST);
        }
        if (CarrierStatusEnum.TRANSPORT.getCode() == info.getStatus()) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.TRANSPORT_NOT_STOP);
        }

        info.setStatus(CarrierStatusEnum.STOP_ORDER.getCode());
        carrierMappingDomainService.updateCarrierMapping(info);
        return Boolean.TRUE;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean startOrder(IdCommand command) {
        CarrierMappingInfo info = carrierMappingDomainService.getCarrierMapingInfo(command.getId());
        if (ObjectUtil.isEmpty(info)) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.DATA_NOT_EXIST);
        }

        info.setStatus(CarrierStatusEnum.FREE.getCode());
        carrierMappingDomainService.updateCarrierMapping(info);
        return Boolean.TRUE;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean carrierUnbind(CarrierUnbindCommand command) {
        CarrierMappingInfo info = carrierMappingDomainService.getCarrierMapingInfo(command.getId());
        if (ObjectUtil.isEmpty(info)) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.DATA_NOT_EXIST);
        }
        if (CarrierStatusEnum.TRANSPORT.getCode() == info.getStatus()) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.TRANSPORT_NOT_UNBIND);
        }
        //carrier_mapping解绑
        carrierMappingDomainService.carrierUnbind(command.getId());
        //group_mapping 删除
        if (Objects.nonNull(command.getGroupId())) {
            carrierGroupDomainService.deleteGroupMapping(command.getGroupId());
        }
        return Boolean.TRUE;
    }

    /**
     * 1.查询组信息
     * 2.遍历list
     * 3.删除原来组映射关系
     * 4.添加新的映射关系
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean changeGroup(CarrierGroupChangeCommand command) {
        CarrierGroupInfo info = carrierGroupDomainService.groupInfo(command.getGroupId());
        if (ObjectUtil.isEmpty(info)) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.DATA_NOT_EXIST);
        }
        log.info("changeGroup command= {}", JsonUtil.toJson(command));
        List<CarrierMappingChangeCommand> carrierMappingChangeCommandList = command.getList();
        log.info("changeGroup carrierMappingChangeCommandList= {}", JsonUtil.toJson(carrierMappingChangeCommandList));
        for (CarrierMappingChangeCommand carrierMappingChangeCommand : carrierMappingChangeCommandList) {
            Long carrierMappingId = carrierMappingChangeCommand.getId();
            Long groupMappingId = carrierMappingChangeCommand.getGroupMappingId();
            //原来有组映射关系，则先删除
            if (Objects.nonNull(groupMappingId)) {
                carrierGroupDomainService.deleteGroupMapping(groupMappingId);
            }
            if (Objects.nonNull(carrierMappingId)) {
                //新增组映射关系
                carrierGroupDomainService.addGroupMapping(carrierMappingId, command.getGroupId(), command.getUserId());
            }
        }
        return Boolean.TRUE;
    }

    public PageInfoDTO<CarrierGroupInfoDTO> groupList(IdQuery query) {
        return carrierGroupDomainService.groupList(query);
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean addCarrier(CarrierAddCommand command) {
        if (Objects.nonNull(command.getGroupId())) {
            CarrierGroupInfo groupInfo = carrierGroupDomainService.groupInfo(command.getGroupId());
            if (ObjectUtil.isEmpty(groupInfo)) {
                throw new CarrierUserException(CarrierUseErrorCodeEnum.DATA_NOT_EXIST);
            }
        }

        CarrierMappingInfo info = new CarrierMappingInfo();
        info.setVehicleId(command.getVehicleId());
        info.setCarrierId(command.getUserId());
        List<CarrierMappingInfo> mappingList = carrierMappingDomainService.getMappingList(info);
        if (CollectionUtils.isEmpty(mappingList)) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.DATA_NOT_EXIST);
        }

        CarrierMappingInfo mappingInfo = mappingList.get(0);
        if (ObjectUtil.isNotEmpty(mappingInfo.getDriverId())) {
            throw new CarrierUserException(CarrierUseErrorCodeEnum.DRIVER_BINDED_VIHICLE);
        }

        // 绑定车辆与司机
        mappingInfo.setDriverId(command.getDriverId());
        mappingInfo.setUpdateTime(new Date());
        carrierMappingDomainService.updateCarrierMapping(mappingInfo);

        // 添加到分组
        if (Objects.nonNull(command.getGroupId())) {
            carrierGroupDomainService.addGroupMapping(mappingInfo.getId(), command.getGroupId(), command.getUserId());
        }
        return Boolean.TRUE;
    }

    public List<VehicleInfoDTO> getUnBindVehicle(UserIdQuery query) {
        return KcBeanConverter.toList(vehicleInfoDomainService.getUnBindVehicles(query), VehicleInfoDTO.class);
    }

    public List<CarrierDTO> getUnBindDriver(UserIdQuery query) {
        log.info("开始查询未绑定司机 getUnBindDriver  【参数】 query = {}", JsonUtil.toJson(query));
        // 获取当前用户下的所有司机
        List<CarrierInfo> infos = carrierInfoDomainService.getCarrierDrivers(query);
        log.info("查询用户下所有司机 getCarrier  【参数】 query = {}, 【查询出名下司机】 infos = {}", JsonUtil.toJson(query), JsonUtil.toJson(infos));
        if (infos.isEmpty()) {
            return Collections.emptyList();
        }
        //把认证通过的过滤出来
       // infos = infos.stream().filter(carrierInfo -> AuditAuthenticationStatusEnum.SUCCESS.getCode() == carrierInfo.getAuthenticationStatus()).collect(Collectors.toList());
       // log.info("过滤认证通过司机 【参数】 query = {}, 【过滤认证通过的司机】 infos = {}", JsonUtil.toJson(query), JsonUtil.toJson(infos));
        //获取未绑定车辆的司机id
        List<Long> unBindVehicleDriverIds = getUnBindVehicleDriverId(query);
        log.info("查询未绑定司机id列表 getUnBindVehicleDriverId  【参数】 query = {}, 【未绑定车辆的司机id列表】 unBindVehicleDriverIds = {}", JsonUtil.toJson(query), JsonUtil.toJson(unBindVehicleDriverIds));
        if (unBindVehicleDriverIds.isEmpty()) {
            return Collections.emptyList();
        }
        ArrayList<CarrierInfo> carrierInfos = new ArrayList<>();
        Map<Long, CarrierInfo> infoMap = infos.stream().collect(Collectors.toMap(CarrierInfo::getId, Function.identity()));
        log.info("查询用户下所有司机 转map, 【名下所有司机列表】= {}， 【转成的map】= {}", JsonUtil.toJson(infos), JsonUtil.toJson(infoMap));
        //筛选出未绑定车辆司机信息
        infoMap.keySet().forEach(id -> {
            if (unBindVehicleDriverIds.contains(id)) {
                carrierInfos.add(infoMap.get(id));
            }
        });
        log.info("最终返回未绑定司机信息列表 【名下所有司机列表】= {}， 【查询未绑定司机id列表】= {}， 【转成的map】= {}", JsonUtil.toJson(infos), JsonUtil.toJson(unBindVehicleDriverIds), JsonUtil.toJson(infoMap));
        return KcBeanConverter.toList(carrierInfos, CarrierDTO.class);
    }

    /**
     * 根据userId获取名下未绑车辆司机di列表
     */
    private List<Long> getUnBindVehicleDriverId(UserIdQuery query) {
        //获取名下司机id列表
        List<Long> driverIds = carrierDriverDomainService.queryDriverIdListByUserId(query.getUserId());
        if (driverIds.isEmpty()) {
            return driverIds;
        }
        // 获取当前用户下的绑定车辆的司机
        List<Long> bindVehicleDriverIds = carrierMappingDomainService.queryDriverIdsByCarrierId(query.getUserId());
        if (bindVehicleDriverIds.isEmpty()) {
            return driverIds;
        }
        //去除绑定车辆的司机id
        return driverIds.stream().filter(id -> !bindVehicleDriverIds.contains(id)).collect(Collectors.toList());
    }

    /**
     * 获取用户的运力列表
     * <p>
     * 本来一条sql就能满足，只是需要多表联合，拆分多表联合增加了很多代码逻辑，也增加了更多的数据库查询，建议宽表处理
     */
    public PageInfoDTO<CarrierListDTO> getCarrierListForUser(CarrierListQuery query) {
       /* List<Long> carrierMappingIds = new ArrayList<>(30);
        List<Long> mappingIdsForGroup = new ArrayList<>(30);
        Map<Long, GroupMappingInfo> groupMappingInfoMap = new HashMap<>();
        if (Objects.nonNull(query.getGroupId())) {
            //分组id不为空，查询组映射列表
            List<GroupMappingInfo> groupMappingList = carrierGroupDomainService.queryMappingByGroupIdAndUser(query.getGroupId(), query.getUserId());
            //分组id不为空，组映射列表为空则直接返回
            if (groupMappingList.isEmpty()) {
                return new PageInfoDTO<>(0, query.getCurPagerNo(), query.getPageSize(), Collections.emptyList());
            }
            //组映射列表转map
            groupMappingInfoMap = groupMappingList.stream().collect(Collectors.toMap(GroupMappingInfo::getMappingId, Function.identity()));
            //获取分组映射里的运力映射id列表
            mappingIdsForGroup.addAll(groupMappingList.stream().map(GroupMappingInfo::getMappingId).collect(Collectors.toList()));
        }
        //根据车主，车辆相关条件查询映射信息
        List<CarrierMappingInfo> userAndVehicleMappingList = carrierMappingDomainService.queryByVehicleParamAndUser(query);
        if (!userAndVehicleMappingList.isEmpty()) {
            carrierMappingIds.addAll(userAndVehicleMappingList.stream().map(CarrierMappingInfo::getId).collect(Collectors.toList()));
        }
        //根据车主，司机相关条件查询映射信息
        List<CarrierMappingInfo> userAndCarrierMappingList = carrierMappingDomainService.queryByCarrierParamAndUser(query);
        if (!userAndCarrierMappingList.isEmpty()) {
            for (CarrierMappingInfo carrierMappingInfo : userAndCarrierMappingList) {
                if (Objects.nonNull(carrierMappingInfo.getDriverId())) {
                    carrierMappingIds.add(carrierMappingInfo.getId());
                }
            }
        }
        //根据组数据、司机、车辆等查询结果再去查询运力关系表并分页
        CarrierMapCondition condition = KcBeanConverter.toBean(query, CarrierMapCondition.class);
        if (!mappingIdsForGroup.isEmpty()) {
            //运力组不为空
            if (!carrierMappingIds.isEmpty()) {
                //用户groupMapping数据去过滤
                List<Long> afterFilterGroupIds = carrierMappingIds.stream().filter(mappingIdsForGroup::contains).collect(Collectors.toList());
                condition.setIds(afterFilterGroupIds);
            } else {
                condition.setIds(mappingIdsForGroup);
            }
        } else {
            condition.setIds(carrierMappingIds);
        }
        //真正去查询分页
        KcPage<CarrierMappingInfo> mappingKcPage  = carrierMappingDomainService.queryMappingPageByCondition(condition);
        //开始处理分页后数据
        if (Objects.isNull(mappingKcPage) || mappingKcPage.getList().isEmpty()) {
            return new PageInfoDTO<>(0, query.getCurPagerNo(), query.getPageSize(), Collections.emptyList());
        }
        PageInfoDTO<CarrierListDTO> pageInfoDTO = KcPageConverter.toPageInfoDTO(mappingKcPage, CarrierListDTO.class);
        //最后组装数据返回
        List<CarrierListDTO> resultDtoList = pageInfoDTO.getList();
        for (CarrierListDTO carrierListDTO : resultDtoList) {
            //运力状态
            carrierListDTO.setCarrierStatus(carrierListDTO.getStatus());
            //查询司机信息
            CarrierInfo carrierInfo = carrierInfoDomainService.queryByCarrierId(carrierListDTO.getDriverId());
            //设置司机信息
            carrierListDTO.setMobile(carrierInfo.getMobile());
            carrierListDTO.setName(carrierInfo.getName());
            carrierListDTO.setAllowDrivingModel(carrierInfo.getAllowDrivingModel());
            //查询车辆信息
            VehicleInfo vehicleInfo = vehicleInfoDomainService.queryById(carrierListDTO.getVehicleId());
            //设置车辆信息
            carrierListDTO.setLoads(vehicleInfo.getLoads());
            carrierListDTO.setPlateColor(vehicleInfo.getPlateColor());
            carrierListDTO.setPlateNumber(vehicleInfo.getPlateNumber());
            carrierListDTO.setVehicleCategory(vehicleInfo.getVehicleCategory());
            carrierListDTO.setVehicleType(vehicleInfo.getVehicleType());
            //设置组映射id
            GroupMappingInfo groupMappingInfo = groupMappingInfoMap.get(carrierListDTO.getId());
            if (Objects.nonNull(groupMappingInfo)) {
                carrierListDTO.setGroupId(groupMappingInfo.getId());
            }
        }
        return pageInfoDTO;*/
        return KcPageConverter.toPageInfoDTO(carrierInfoDomainService.getCarrierList(query), CarrierListDTO.class);
    }
}
